#ifndef WORKER_GROUP_H_
#define WORKER_GROUP_H_

#include <Worker.hh>
#include "Group.hh"

//
/**
 * \file GroupWorker.hh
 * \author  jsk <jsk.jinsubkim@gmail.com>
 * \version 1.0
 *
 * \class GroupWorker GroupWorker.hh
 *
 * 여러 워커들과 협력해서 사용자가 할당한 작업(Task)을 수행한다.
 * 기존 Worker 클래스와 다르게 GroupWorker 클래스는 다른 워커와 협력할 
 * 수 있는 기능을 추가하였다.
 * 
 * 첫째, 스레드 종료와 함께 인스턴스 삭제 기능. 이 기능은 스레드를 관리해야 
 * 하는 불편함을 줄이기 위해서 스스로 제거해서 동작하는 스레드만 관리하도록 
 * 한다.
 * 
 * 둘째, 큐를 비우지 않고 스레드 종료. 협력하는 스레드 개수를 조절하고 싶을 
 * 경우에 스레드를 삭제할 수 있어야 한다. 기존 Worker 클래스에서는 큐를 
 * 비워야지만 스레드가종료되었기 때문에 
 * 
 * 셋째, 최소 스레드 유지. 블럭킹 큐의 타임아웃 설정에 따라서 워커가 작업을
 * 대기 하다가 종료될 수 있다. 현재 그룹에 포함된 워커 개수가 그룹에서 최소한 
 * 유지할 스레드 개수보다 작은 것은 용납되지 않기 때문에 
 */
class GroupWorker : public Worker
{
public:
	/**
	 * \name GroupWorker
	 */
	GroupWorker(BlockingQueue* AssignedQueue, Group* AssignedGroup);
	
	/**
	 * \name ~GroupWorker
	 */
	~GroupWorker();
	
// Worker
protected:
	/**
	 * \name doWorking
	 * 
	 * 작업을 수행한다.
	 * 
	 * 지정된 큐에서 작업을 하나씩 가져와 처리한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf doWorking();
	
	/**
	 * \name handleTask
	 * 
	 * 작업을 처리한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf handleTask(Task* AssignedTask);
	
	/**
	 * \name finalizeTask
	 * 
	 * 작업을 마무리 짓는다.
	 * 
	 * 그룹에 다른 워커가 있을 경우에는 작업을 위탁하고 끝낸다.
	 * 반대로 다른 워커가 없을 경우에 작업을 마무리 짓는다. 
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf finalizeTask();
	
	/**
	 * \name entrustTask
	 * 
	 * 작업을 위탁한다.
	 * 
	 * 큐에 작업이 있던지 상관하지 않고, 종료한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf entrustTask();
	
// Thread
protected:
	/**
	 * \name resign
	 * 
	 * 스레드가 종료하였을 때 행동을 취한다.
	 * 
	 * Worker::resign 메소드를 호출하고, 자신을 제거한다.
	 * 
	 * \warning
	 * 
	 * 함수 종료 이후에 인스턴스의 메로리에 접근하면 폴트 난다.
	 *
	 * \see Worker::resign 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf resign();
	
// Member
protected:
	/**
	 * 그룹에 포함된 워크를 엮는 리스트.
	 */
	Group* JoinedGroup;
	
	/**
	 * 그룹에서의 자신의 아이디.
	 */
	WID IdWithinGroup;
};

#endif //WORKER_GROUP_H_